//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <string.h>
#include <ddkit.h>
#include "windef.h"
#include "xllp_dmac.h"
#include "xllp_gpio.h"
#include "xllp_lcd.h"
#include "xllp_camera.h"
#include "xllp_ADCM2650.h"
#include "Bvd1BD.h"
#include "xllp_ci.h"
#include "drv_glob.h"
#include "display.h"
#include "_display.h"
int kprintf(const char *, ...);

extern Display_Address g_dispAddr;
void LCDInitToshibaQVGA(P_XLLP_LCD_T pXllpLCD);
void LCDOffToshibaQVGA(P_XLLP_LCD_T pXllpLCD);
void KeypadInitLED(P_XLLP_LCD_T pXllpLCD);
void KeypadOffLED(P_XLLP_LCD_T pXllpLCD);

XLLP_LCD_T XllpLCD;

XLLP_OVERLAY_T XllpOverlay1, XllpOverlay2;

volatile LCDRegs		* v_pLcdRegs = NULL;
volatile XLLP_CLKMGR_T	* v_pClkRegs = NULL;
volatile XLLP_GPIO_T	* v_pGPIORegs = NULL;
volatile unsigned int   * v_pOSTRegs = NULL;

Boolean MapVirtualAddress()
{
//  v_pDMAC = (P_XLLP_DMAC_T)DMAC_BASE_C_VIRTUAL;

//  v_pI2C = (volatile unsigned int *)I2C_BASE_C_VIRTUAL;

    v_pOSTRegs = (volatile unsigned int *)((int)v_PerifBase + OST_OFFSET);
//  v_pCIRegs = (volatile unsigned int *)CMRA_BASE_C_VIRTUAL;

    v_pLcdRegs = (volatile LCDRegs *)((int)v_PerifBase + 0x04000000);

	v_pClkRegs = (volatile XLLP_CLKMGR_T *)((int)v_PerifBase + CLK_OFFSET);

	v_pGPIORegs = (volatile XLLP_GPIO_T *)((int)v_PerifBase + GPIO_OFFSET);

	// The GDI will use the section mapped address for the frame buffer.
	// The cacheable/bufferable attributes are configured above in the call to ConfigureFrameBufferSectionDescriptor().

//	v_pBoardLevelRegister=(volatile BLR_REGS *)FPGA_REGS_BASE_C_VIRTUAL;

	return TRUE;
}

INLINE void ClearFrameBuffer()
{
    memset((void *)g_dispAddr.vaBasePlane, 0, BASEPLANE_FB_SIZE);
}

#if 0
void FillFrameBuffer(int page, int color)
{
    unsigned int *fbp;
    unsigned int i;
    unsigned int frameBufferSize = LCD_WIDTH * LCD_HEIGHT * BASEPLANE_PIXELBYTES;
    fbp = (unsigned int *)(g_dispAddr.vaBasePlane+(page*frameBufferSize));
    for ( i = 0; i < (frameBufferSize>>2); i++) {
        *fbp++ = color;
    }
}
#endif



void DispDrvrInitialize()
{
	MapVirtualAddress();

	XllpLCD.DisplayType = TOSHIBAQVGARGB;
	XllpLCD.GPIO =  (XLLP_VUINT32_T *) v_pGPIORegs;
	XllpLCD.CLKMan = (XLLP_VUINT32_T *) v_pClkRegs;
	XllpLCD.LCDC = (XLLP_VUINT32_T *) v_pLcdRegs;
	XllpLCD.OST  =   (XLLP_VUINT32_T *) v_pOSTRegs;
	XllpLCD.FrameBufferWidth = LCD_WIDTH;
	XllpLCD.FrameBufferHeight = LCD_HEIGHT;
#ifdef RGBT666PACKED_ENABLE
    XllpLCD.BPP = BPP_19_PACKED;
#else
    XllpLCD.BPP = BPP_19;
#endif

	XllpLCD.PixelDataFormat = PDFOR_11;  //with overlays enabled use PDFOR_11 for 19bpp
	XllpLCD.CurrentPage = 0;

	XllpLCD._FRAME_BUFFER_BASE_PHYSICAL = g_dispAddr.paBasePlane;
	XllpLCD._DMA_CHANNEL_0_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan0Desc;
	XllpLCD.frameDescriptorCh0fd1 = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan0Desc;

    // Initialize the GPIO registers for KeyOad LED operation
    KeypadInitLED(&XllpLCD);
	// Initialize the GPIO registers for proper LCD Controller operation
    //XllpLCDInit(&XllpLCD);
    //LCDInitToshibaQVGA(&XllpLCD);

//    ClearFrameBuffer();

	return;
}

EXTERN_C Boolean ConfigureOverlay1(OverlayFormat *overlay1, Boolean bEnable)
{
    if(bEnable) {  // Enable Overlay1
        XllpLCD._DMA_CHANNEL_1_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan1Desc;
        XllpLCD._DMA_CHANNEL_1_ALT_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan1AltDesc;
        XllpLCD._PALETTE_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paPaletteDesc;

	    XllpLCD.frameDescriptorCh1 = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan1Desc;
	    XllpLCD.frameDescriptorCh1fd2 = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan1AltDesc;
        XllpLCD.frameDescriptorPalette = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaPaletteDesc;

        XllpLCD._OVERLAY1_CHANNEL_BASE_PHYSICAL = g_dispAddr.paOverlay1;
        XllpLCD._PALETTE_BUFFER_BASE_PHYSICAL = g_dispAddr.paPalette;

        // This is used for RGB mode
        switch(overlay1->Bpp)
		{
			case 4:
				XllpOverlay1.OverlayBPP = 0x2;
				break;
			case 8:
				XllpOverlay1.OverlayBPP = 0x3;
				break;
			case 16:
				XllpOverlay1.OverlayBPP = 0x4;
				break;
			case 18:           //unpacked 18 bits
				XllpOverlay1.OverlayBPP = 0x5;
				break;
		    case 19:           //unpacked 19 bits
				XllpOverlay1.OverlayBPP = 0x7;
				break;
			case 24:
			    XllpOverlay1.OverlayBPP = 0x9;
				break;
		    default:
		        XllpOverlay1.OverlayBPP = 0x5;
			    break;
		}

		switch(overlay1->Color)
		{
            case COLOR_RGB4:
            case COLOR_RGB8:
            case COLOR_RGB565:
            case COLOR_RGBT666:
		        XllpOverlay1.Format = FORMAT_RGB;
		        break;

		    default:
		        kprintf("Unsupported format for overlay1 now!\n");
		        return FALSE;
		}

        XllpOverlay1.OverlayWidth = overlay1->Width;
        XllpOverlay1.OverlayHeight = overlay1->Height;
        XllpOverlay1.X_Position = overlay1->PosX;
        XllpOverlay1.Y_Position = overlay1->PosY;

        XllpLCD_Overlay1_Enable(&XllpLCD, &XllpOverlay1);
    }
    else {                      // Disable Overlay1
        XllpLCD_Overlay1_Disable(&XllpLCD, &XllpOverlay1);
    }

    return TRUE;
}



EXTERN_C Boolean ConfigureOverlay2(OverlayFormat *overlay2, Boolean bEnable)
{
    if(bEnable) {  // Enable Overlay2
        XllpLCD._DMA_CHANNEL_2_Y_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan2Desc;
        XllpLCD._DMA_CHANNEL_3_Cb_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan3Desc;
        XllpLCD._DMA_CHANNEL_4_Cr_FRAME_DESCRIPTOR_BASE_PHYSICAL = g_dispAddr.paChan4Desc;

        XllpLCD.frameDescriptorCh2_YCbCr_Y = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan2Desc;
		XllpLCD.frameDescriptorCh3_YCbCr_Cb = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan3Desc;
		XllpLCD.frameDescriptorCh4_YCbCr_Cr = (volatile LCD_FRAME_DESCRIPTOR *)g_dispAddr.vaChan4Desc;

        XllpLCD._OVERLAY2_Y_CHANNEL_BASE_PHYSICAL = g_dispAddr.paOverlay2Y;
        XllpLCD._OVERLAY2_Cb_CHANNEL_BASE_PHYSICAL = g_dispAddr.paOverlay2Cb;
        XllpLCD._OVERLAY2_Cr_CHANNEL_BASE_PHYSICAL = g_dispAddr.paOverlay2Cr;

#if 0
        // This is only used for RGB, and the driver only uses YCbCr now.
        switch(overlay2->Bpp)
		{
			case 4:
				XllpOverlay2.OverlayBPP = 0x2;
				break;
			case 8:
				XllpOverlay2.OverlayBPP = 0x3;
				break;
			case 16:
				XllpOverlay2.OverlayBPP = 0x4;
				break;
			case 18:           //unpacked 18 bits
				XllpOverlay2.OverlayBPP = 0x5;
				break;
		    case 19:           //unpacked 19 bits
				XllpOverlay2.OverlayBPP = 0x7;
				break;
			case 24:
			    XllpOverlay2.OverlayBPP = 0x9;
				break;
		default:
		    XllpOverlay2.OverlayBPP = 0x5;
			break;
		}
#endif

		switch(overlay2->Color)
		{
		    case COLOR_YCbCr422:
		        XllpOverlay2.Format = FORMAT_PLANAR_422;
		        break;
		    case COLOR_YCbCr420:
		        XllpOverlay2.Format = FORMAT_PLANAR_420;
		        break;

		    // case FORMAT_RGB:
            // case FORMAT_PACKED_444:
            // case FORMAT_PLANAR_444:
		    default:
		        kprintf("Unsupported format for overlay2 now!\n");
		        return FALSE;
		}

        XllpOverlay2.OverlayWidth = overlay2->Width;
        XllpOverlay2.OverlayHeight = overlay2->Height;
        XllpOverlay2.X_Position = overlay2->PosX;
        XllpOverlay2.Y_Position = overlay2->PosY;

        XllpLCD_Overlay2_Enable(&XllpLCD, &XllpOverlay2);
    }
    else {                      // Disable Overlay2
        XllpLCD_Overlay2_Disable(&XllpLCD, &XllpOverlay2);
    }

    return TRUE;
}


EXTERN_C void LCD_Suspend(int SuspendType, int VGAOff)
{
    if (VGAOff) {
        LCDOffToshibaQVGA(&XllpLCD);
    }
    XllpLCDSuspend(&XllpLCD, SuspendType);
}


EXTERN_C void LCD_Resume(int VGAOn)
{
    XllpLCDResume(&XllpLCD);
    if (VGAOn) {
        LCDInitToshibaQVGA(&XllpLCD);
    }
    else {
        ((XLLP_GPIO_T *)(XllpLCD.GPIO))->GPSR0 |= XLLP_GPIO_BIT_PWM_OUT0;
    }
}

